/***********************************************************
 *  File_Name  : XJOCCI.cpp
 *  File_Path   : 
 *  File_Encode : UTF8
 *  Description : Oracle DB OCCI 操作类
 *  
 *  OS : Linux, UNIX
 *  LastVersion  : 20120914
 *      
 *  Author      : LiXiujie(李秀杰)
 *  Date        : 2012-9-14
 *  Version     : 20120914
 *  Description : 
 *                
 *  Edit Author : 
 *  Edit Date   : 
 *  Version     : 
 *  Description :
 *                
 ***********************************************************/
#include "XJOCCI.h"

namespace XJUtilClass{

XJOCCI::XJOCCI() {
	// TODO Auto-generated constructor stub
	m_pExceptionProcessFun = NULL;
	m_pPrintSQLFun = NULL;
	m_pEnv = NULL;
	m_pConnPool = NULL;
	m_pConn = NULL;
	if (getenv("DBUser")){
		m_strDBUser = getenv("DBUser");
	}
	if (getenv("DBPassWD")){
		m_strDBPassWD = getenv("DBPassWD");
	}
	if (getenv("DBName")){
		m_strDBName = getenv("DBName");
	}
	m_nMaxConn = 10;
	m_nMinConn = 5;
	m_nIncrConn = 1;
	m_bAutoCommit=true;
	m_bAutoConn = false;
	m_pPrintSQLFun = 0;
	m_pExceptionProcessFun = 0;
	m_pXJOCCIExceptionProcessData = 0;
}

XJOCCI::XJOCCI(const char *szDBUser,const char *szDBPassWD,const char *szDBName,
		const bool &bAutoConn,const bool &bAutoCommit){
	m_pExceptionProcessFun = NULL;
	m_pEnv = NULL;
	m_pConnPool = NULL;
	m_pConn = NULL;
	if (szDBUser){
		m_strDBUser = szDBUser;
	}
	if (szDBPassWD){
		m_strDBPassWD = szDBPassWD;
	}
	if (szDBName){
		m_strDBName = szDBName;
	}
	m_nMaxConn = 10;
	m_nMinConn = 5;
	m_nIncrConn = 1;
	m_bAutoCommit=bAutoCommit;
	m_bAutoConn = bAutoConn;
	m_pPrintSQLFun = 0;
	m_pExceptionProcessFun = 0;
	m_pXJOCCIExceptionProcessData = 0;
}

XJOCCI::~XJOCCI() {
	// TODO Auto-generated destructor stub
	DestroyConnectionPool();
}

bool XJOCCI::InitConnectionPool(){
	return CreateDBConnPool();
}
bool XJOCCI::DestroyConnectionPool(){
	CloseDBConnPool();
	return true;
}


const char*	XJOCCI::GetDBName(){
	return m_strDBName.c_str();
}
void XJOCCI::SetDBName(const char* szDBName){
	if (szDBName)
		m_strDBName = szDBName;
}
const char*	XJOCCI::GetDBUser(){
	return m_strDBUser.c_str();
}
void XJOCCI::SetDBUser(const char* szDBUser){
	if (szDBUser)
		m_strDBUser = szDBUser;
}
const char*	XJOCCI::GetDBPassWD(){
	return m_strDBPassWD.c_str();
}
void XJOCCI::SetDBPass(const char* szDBPassWD){
	if (szDBPassWD)
		m_strDBPassWD = szDBPassWD;
}
int	XJOCCI::GetMaxConn(){
	return m_nMaxConn;
}
void	XJOCCI::SetMaxConn(int nMaxConn){
	m_nMaxConn = nMaxConn;
}
int	XJOCCI::GetMinConn(){
	return m_nMinConn;
}
void XJOCCI::SetMinConn(int nMinConn){
	m_nMinConn = nMinConn;
}
int	XJOCCI::GetIncrConn(){
	return m_nIncrConn;
}

void XJOCCI::SetIncrConn(int nIncrConn){
	m_nIncrConn = nIncrConn;
}

Environment* XJOCCI::GetEnv(){
	return m_pEnv;
}

ConnectionPool* XJOCCI::GetConnPool(){
	return m_pConnPool;
}

bool XJOCCI::CreateDBConnPool(){
	try{
		if (m_pEnv == NULL)
				m_pEnv = Environment::createEnvironment(Environment::THREADED_MUTEXED);
		if (m_pConnPool == NULL && m_pEnv)
			m_pConnPool = m_pEnv->createConnectionPool(m_strDBUser, m_strDBPassWD, m_strDBName, m_nMinConn, m_nMaxConn, m_nIncrConn);
		if (m_pConnPool && m_bAutoConn && m_pConn == NULL){
			m_pConn = CreateConnection();
		}
	}catch(SQLException &ex){
		ExceptionProcess(ex);
		return false;
	}
	return true;
}

void XJOCCI::CloseDBConnPool(){
	if (m_pConnPool && m_bAutoConn && m_pConn){
		CloseConnection(m_pConn);
		m_pConn = NULL;
	}
	if(m_pConnPool && m_pEnv){
		m_pEnv->terminateConnectionPool(m_pConnPool);
		m_pConnPool = NULL;
	}

	if(m_pEnv){
		Environment::terminateEnvironment(m_pEnv);
		m_pEnv = NULL;
	}
}

Connection* XJOCCI::CreateConnection(){
	Connection *pConn = NULL;
	try
	{
		if (m_pConnPool == NULL)
			CreateDBConnPool();
		if (m_pConnPool)
			pConn = m_pConnPool->createConnection(m_strDBUser, m_strDBPassWD);
	}catch(SQLException &ex){
		ExceptionProcess(ex);
	}
	return pConn;
}

void XJOCCI::CloseConnection(Connection *pConn){
	if(pConn && m_pConnPool && pConn != m_pConn){
		try{
			m_pConnPool->terminateConnection(pConn);
		}catch(SQLException &ex){
			ExceptionProcess(ex);
		}
	}
}

Connection* XJOCCI::GetAutoConn(){
	m_bAutoConn = true;
	CreateDBConnPool();
	return m_pConn;
}
Connection* XJOCCI::SetAutoConn(bool bAutoConn){
	if (bAutoConn){
		return GetAutoConn();
	}else{
		m_bAutoConn = false;
		if (m_pConnPool && m_bAutoConn && m_pConn){
			CloseConnection(m_pConn);
			m_pConn = NULL;
		}
	}
	return NULL;
}

int XJOCCI::AddData(const string& strTableName, const string& strFields, const string& strValues){
	string strSql = "INSERT INTO ";
	strSql += strTableName;
	strSql += " ( ";
	strSql +=strFields;
	strSql += " ) VALUES( ";
	strSql += strValues;
	strSql += ")";
	return Execute(strSql);
}
int XJOCCI::AddData(Connection* pConn,const string& strTableName, const string& strFields, const string& strValues){
	string strSql = "INSERT INTO ";
	strSql += strTableName;
	strSql += " ( ";
	strSql +=strFields;
	strSql += " ) VALUES( ";
	strSql += strValues;
	strSql += ")";
	return Execute(pConn, strSql);
}
int XJOCCI::ModifyData(Connection* pConn,const string& strTableName, const string& strFields, const string& strConditions){
	string strSql = "UPDATE ";
	strSql += strTableName;
	strSql += " SET ";
	strSql += strFields;
	if(strConditions.length() > 0)
	{
		strSql += " WHERE ";
		strSql +=strConditions;
	}
	return Execute(pConn, strSql);
}
int XJOCCI::ModifyData(const string& strTableName, const string& strFields, const string& strConditions){
	string strSql = "UPDATE ";
	strSql += strTableName;
	strSql += " SET ";
	strSql += strFields;
	if(strConditions.length() > 0)
	{
		strSql += " WHERE ";
		strSql +=strConditions;
	}
	return Execute(strSql);
}
int XJOCCI::RemoveData(Connection* pConn,const string& strTableName, const string& strConditions){
	string strSql = "DELETE ";
	strSql += strTableName;
	if(strConditions.length() > 0)
	{
		strSql += " WHERE ";
		strSql +=strConditions;
	}
	return Execute(pConn, strSql);
}
int XJOCCI::RemoveData(const string& strTableName, const string& strConditions){
	string strSql = "DELETE ";
	strSql += strTableName;
	if(strConditions.length() > 0)
	{
		strSql += " WHERE ";
		strSql +=strConditions;
	}
	return Execute(strSql);
}

int XJOCCI::Execute(const string& strSql){
	PrintSQL(strSql);
	InitConnectionPool();
	int nRet = 0;
	Connection *pConn = NULL;
	Statement * pStmt = NULL;
	try
	{
		if (m_bAutoConn){
			pConn = m_pConn;
			if (pConn == NULL){
				return -1;
			}
		}else{
			pConn = CreateConnection();
		}
		pStmt = pConn->createStatement(strSql);
		nRet = pStmt->executeUpdate();
		if(m_bAutoCommit){
			pConn->commit();
		}
	}catch(SQLException &ex){
		if(m_bAutoCommit)
			pConn->rollback();
		ExceptionProcess(ex, strSql);
		nRet = -1;
	}
	if (pStmt && pConn){
		pConn->terminateStatement(pStmt);
		pStmt = NULL;
	}
	if (!m_bAutoConn && pConn){
		CloseConnection(pConn);
		pConn = NULL;
	}
	return nRet;
}
int XJOCCI::Execute(Connection* pConn,const string& strSql){
	int nRet = 0;
	Statement * pStmt = NULL;
	PrintSQL(strSql);
	try
	{
		pStmt = pConn->createStatement(strSql);
		nRet = pStmt->executeUpdate();
		if(m_bAutoCommit){
			pConn->commit();
		}
	}catch(SQLException &ex){
		if(m_bAutoCommit)
			pConn->rollback();
		ExceptionProcess(ex, strSql);
		nRet = -1;
	}
	if (pStmt && pConn){
		pConn->terminateStatement(pStmt);
		pStmt = NULL;
	}
	return nRet;
}
/*
bool XJOCCI::SelectData(const string& strSql, XJOCCIResultSet &xjRS){
	InitConnectionPool();
	bool bRet = true;
	try{
		xjRS.m_pXJOCCI = this;
		xjRS.m_bFreeConn = true;
		if (m_bAutoConn){
			xjRS.m_pConn = m_pConn;
		}else{
			xjRS.m_pConn = CreateConnection();
		}
		xjRS.m_pStmt = xjRS.m_pConn->createStatement(strSql);
		xjRS.m_pRS = xjRS.m_pStmt->executeQuery();
	} catch (SQLException &ex){
		ExceptionProcess(ex, strSql);
		bRet = false;
	}
	if (!bRet){
		xjRS.DeleteRS();
	}
	return bRet;
}

bool XJOCCI::SelectData(Connection* pConn, const string& strSql, XJOCCIResultSet &xjRS){
	bool bRet = true;
	try{
		xjRS.m_pXJOCCI = this;
		xjRS.m_bFreeConn = false;
		xjRS.m_pConn = pConn;
		xjRS.m_pStmt = xjRS.m_pConn->createStatement(strSql);
		xjRS.m_pRS = xjRS.m_pStmt->executeQuery();
	} catch (SQLException &ex){
		ExceptionProcess(ex, strSql);
		bRet = false;
	}
	if (!bRet){
		xjRS.DeleteRS();
	}
	return bRet;
}
*/

void XJOCCI::ExceptionProcess(SQLException &ex,const string &strSql){
	if (m_pExceptionProcessFun)
		m_pExceptionProcessFun(ex, strSql, m_pXJOCCIExceptionProcessData);
	else{
#ifdef __DEBUG__
		cout << "SQL:" <<  strSql << endl;
		cout << "DBErrorCode:" << ex.getErrorCode() << endl;
		cout << "DBErrorMsg:" << ex.getMessage() << endl;
#endif
	}
}
void XJOCCI::PrintSQL(const string &strSql){
	if (m_pPrintSQLFun)
		m_pPrintSQLFun(strSql);
	else{
#ifdef __DEBUG__
		cout << "SQL:" <<  strSql << endl;
#endif
	}
}
}// XJUtilClass
